package umich.max.geolocation.featextract.counter;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;

import max.nlp.wrappers.stanford.StanfordNLP;

public class LIWCCounter extends Counter {

	private static LIWCCounter self = null;

	/*
	 * Each key is a pattern (using Kleene stars), and each value is a LIWC
	 * pattern
	 */
	private static HashMap<String, String> liwcPatterns = new HashMap<String, String>();
	private static StanfordNLP stanford = StanfordNLP.getInstance();
	private HashSet<String> liwcCategories = new HashSet<String>();

	private LIWCCounter() {
		readInWordFile("/home/max/resources/liwc/LIWC.all.txt");
	}

	public static LIWCCounter getInstance() {
		if (self == null)
			self = new LIWCCounter();
		return self;
	}

	public void readInWordFile(String file) {
		try {
			BufferedReader b = new BufferedReader(
					new FileReader(new File(file)));
			String line = "";
			while ((line = b.readLine()) != null) {
				String[] data = line.split(",");
				if (data.length == 2) {
					String startingPattern = data[0].trim().replaceAll("\\*",
							"");
					String type = data[1];
					liwcPatterns.put(startingPattern, type);
					liwcCategories.add(type);
				}
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @param word
	 *            , must be lowercase
	 * @return null, or the matching LIWC pattern
	 */
	public String findCategory(String word) {
		for (Entry<String, String> liwcEntry : liwcPatterns.entrySet()) {
			String prefix = liwcEntry.getKey();
			if (word.startsWith(prefix))
				return liwcEntry.getValue();
		}
		return null;
	}

	public HashMap<String, Integer> getCategoryCountsOfText(String text) {
		HashMap<String, Integer> counts = new HashMap<String, Integer>();
		List<String> words = stanford.convertTextToTokens(text);
		for (String category : liwcCategories) {
			for (String word : words) {
				String matchingCategory = findCategory(word);
				if (matchingCategory != null) { // returns null if no match
					Integer countForCategory = counts.get(matchingCategory);
					if (countForCategory == null)
						counts.put(category, 1);
					else
						counts.put(category, countForCategory + 1);
				}
			}
		}
		return counts;
	}

	public static void main(String[] args) {
		LIWCCounter counter = LIWCCounter.getInstance();
		HashMap<String, Integer> counts = counter
				.getCategoryCountsOfText("November has always been a time for me to think about family and family history.  From Day of the Dead to Thanksgiving, it just feels like a month for reconnecting with living family and remembers those who have passed on. My favorite part about family trees is that they give kids a visual reference for how everyone is related.  I remember as a little kid that figuring out which grandparents, aunts, uncles, etc. went with who and why some knew each other and others didnt was sometimes a little confusing.  So I decided to make a very simple family tree with Chiquita. I just had Chiquita tape everything up to a door in a part of the house where we could leave it and look at it during the month.  We started with the literal tree - first the trunk and a few leafy bunches. We made it small enough that there will be plenty of room to add more to our tree. Then we added a photo of her at the base, Mommy & Daddy at the fork in the tree, Mommys parents on one side and Daddys parents on the other.  We added a few more leafy bunches to make room for Mommy's grandparents above Grandma & Grandpa.  As a final touch Chiquita added some flowers to our tree for decoration. We don't have photos for Daddy's side so we need to make some requests before we can grow our tree taller, but my hope is to keep this up until we get more photos.");
		for (Entry<String, Integer> e : counts.entrySet()) {
			System.out.println(e);
		}
	}
}
